/*
 *
 *  Copyright 2017-2019 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 */
package com.jingtai.platform.config;
//package springfox.springconfig;

import com.fasterxml.classmate.ResolvedType;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.jingtai.validate.swagger.CApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.schema.Collections;
import springfox.documentation.schema.Enums;
import springfox.documentation.schema.Example;
import springfox.documentation.service.AllowableValues;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.EnumTypeDeterminer;
import springfox.documentation.spi.service.ParameterBuilderPlugin;
import springfox.documentation.spi.service.contexts.ParameterContext;
import springfox.documentation.spring.web.DescriptionResolver;
import springfox.documentation.swagger.schema.ApiModelProperties;

import java.util.ArrayList;
import java.util.List;

import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static springfox.documentation.swagger.common.SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER;
import static springfox.documentation.swagger.readers.parameter.Examples.examples;

/**
 * @see http://springfox.github.io/springfox/docs/current/#plugins
 * @author zhengchao
 * @date 2020年4月6日
 *
 */
@Component("swaggerCApiParameterDescriptionReader")
@Order(SWAGGER_PLUGIN_ORDER + 1)
//@Component
//@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000) //<1>
public class CApiParamReader implements ParameterBuilderPlugin {

	private final DescriptionResolver descriptions;// resolver
	private final EnumTypeDeterminer enumTypeDeterminer;

	@Autowired
	public CApiParamReader(DescriptionResolver descriptions, EnumTypeDeterminer enumTypeDeterminer) {
		this.descriptions = descriptions;
		this.enumTypeDeterminer = enumTypeDeterminer;
	}

	@Override
	public void apply(ParameterContext context) {
		Optional<CApiParam> apiParam = context.resolvedMethodParameter().findAnnotation(CApiParam.class);
		context.parameterBuilder().allowableValues(
				allowableValues(context.alternateFor(context.resolvedMethodParameter().getParameterType()),
						apiParam.transform(toAllowableValue()).or("")));
		if (apiParam.isPresent()) {
			CApiParam annotation = apiParam.get();
			StringBuffer description = new StringBuffer();
			description.append(emptyToNull(descriptions.resolve(annotation.value())));
			// description.append(emptyToNull(descriptions.resolve(annotation.comment())));
			List<String> defCheckList = new ArrayList<>();
			if (annotation.required()) {
				defCheckList.add("必填");
			} else {
				defCheckList.add("选填");
			}
			if (annotation.cNotEmpty()) {
				defCheckList.add("不允许为空");
			}
			if (annotation.cEmail()) {
				defCheckList.add("邮箱格式");
			}
			if (annotation.cPhone()) {
				defCheckList.add("手机号码格式");
			}
			if (annotation.cIntMax() != Integer.MAX_VALUE) {
				defCheckList.add("整数最大值:" + annotation.cIntMax());
			}
			if (annotation.cIntMin() != Integer.MIN_VALUE) {
				defCheckList.add("整数最小值:" + annotation.cIntMin());
			}
			if (annotation.cStrMaxLen() != Integer.MAX_VALUE) {
				defCheckList.add("字符串最长:" + annotation.cIntMax());
			}
			if (annotation.cStrMinLen() != 0) {
				defCheckList.add("字符串最短:" + annotation.cStrMinLen());
			}
			if (org.apache.commons.lang3.StringUtils.isNotBlank(annotation.cregexp())) {
				defCheckList.add("正则要求:" + annotation.cregexp());
			}
			description.append("  " + defCheckList.toString());

			context.parameterBuilder().name(emptyToNull(annotation.name()))
					// .description(emptyToNull(descriptions.resolve(annotation.value()))+"abcdefa")
					.description(description.toString()).parameterAccess(emptyToNull(annotation.access()))
					.defaultValue(emptyToNull(annotation.defaultValue())).allowMultiple(annotation.allowMultiple())
					.allowEmptyValue(annotation.allowEmptyValue()).required(annotation.required())
					.scalarExample(new Example(annotation.example())).complexExamples(examples(annotation.examples()))
					.hidden(annotation.hidden()).collectionFormat(annotation.collectionFormat())
					.order(SWAGGER_PLUGIN_ORDER);
		}
	}

	private Function<CApiParam, String> toAllowableValue() {
		return new Function<CApiParam, String>() {
			@Override
			public String apply(CApiParam input) {
				return input.allowableValues();
			}
		};
	}

	private AllowableValues allowableValues(ResolvedType parameterType, String allowableValueString) {
		AllowableValues allowableValues = null;
		if (!isNullOrEmpty(allowableValueString)) {
			allowableValues = ApiModelProperties.allowableValueFromString(allowableValueString);
		} else {
			if (enumTypeDeterminer.isEnum(parameterType.getErasedType())) {
				allowableValues = Enums.allowableValues(parameterType.getErasedType());
			}
			if (Collections.isContainerType(parameterType)) {
				allowableValues = Enums
						.allowableValues(Collections.collectionElementType(parameterType).getErasedType());
			}
		}
		return allowableValues;
	}

	@Override
	public boolean supports(DocumentationType delimiter) {
		return true;
	}

}
